package pl.com.qapps.unity;

import java.io.IOException;

import pl.com.qapps.unity.UnityPb.ItemPb;
import pl.com.qapps.unity.UnityPb.LauncherProperty;
import pl.com.qapps.unity.UnityPb.PropertyValue;
import pl.com.qapps.unity.UnityPb.RequestPb;
import pl.com.qapps.unity.UnityPb.RequestPb.Type;
import pl.com.qapps.unity.UnityPb.ResponsePb;
import pl.com.qapps.unity.UnityPb.ResponsePb.Status;

/**
 * 
 * @author Jakub Dykowski
 * 
 */
final class LauncherProxy {

	private final String appName;

	LauncherProxy(String appName) throws AppNotFoundException,
			LauncherException {

		assert appName != null : "appName cannot be null";
		this.appName = appName;

		try {
			Unity.connect();
		} catch (IOException e) {
			throw new LauncherException("failed to initialize launcher", e);
		}
	}

	String getAppName() {
		return appName;
	}

	void set(LauncherProperty name, PropertyValue value)
			throws LauncherException {
		assert name != null : "name is null";
		assert value != null : "value is null";
		send(RequestPb.newBuilder().setType(Type.SET).setProperty(name)
				.setValue(value).setApp(appName).build());
	}

	PropertyValue get(LauncherProperty property) throws LauncherException {
		ResponsePb res = send(RequestPb.newBuilder().setType(Type.GET)
				.setProperty(property).setApp(appName).build());

		if (!res.hasValue())
			// TODO make better exception handling
			throw new LauncherException(
					"internal communication error, no value returned", true);
		return res.getValue();
	}

	void update(ItemPb item) throws LauncherException {
		if (item == null)
			throw new NullPointerException("item cannot be null");
		PropertyValue value = PropertyValue.newBuilder().setItem(item).build();
		send(RequestPb.newBuilder().setApp(appName).setType(Type.UPDATE_ITEM)
				.setValue(value).build());
	}

	private ResponsePb send(RequestPb req) {
		ResponsePb res;
		try {
			res = Unity.connect().send(req);
			if (res.getResult() == Status.FAILURE) {
				// TODO make better exception handling
				if (res.hasImpl()) {
					if (res.getImpl())
						throw new LauncherException("Implementation error: "
								+ res.getErrorMessage(), res.getImpl());
					else
						throw new LauncherException(res.getErrorMessage(),
								res.getImpl());
				}
				throw new LauncherException(res.getErrorMessage());
			}
			return res;
		} catch (IllegalStateException | IOException e) {
			// TODO make better exception handling
			throw new LauncherException("failed to update item status", e);
		}
	}
}
